# 频数分析
import json
import numpy as np
import model.model as ut
import pandas as pd
import utils.wjx.wjx_explain_v2 as wjx_explain_v2
from enums.sys_type_enum import SysTypeEnum
import re
from collections import Counter
from utils.wjx.common_obj import GenerateObj


def do_analysis(df: pd.DataFrame, index_name_json):
    """

    :param df: 需要分析的数据结构
    :param index_name_json: 索引的名字和表题的映射表格
    :return:
    """

    def get_result(obj: pd.DataFrame) -> []:
        """
        获取前端需要的结结构
        :param obj:
        :return:
        """
        output = []
        for index, row in obj.iterrows():
            output.append({'row_key': str(index), 'values': {str(col): row[col] for col in obj.columns}})
        return output

    def frequency_analysis(inner_df: pd.DataFrame):
        counts = inner_df.value_counts().sort_values()
        frequencies = counts / counts.sum()
        # 输出结果
        res = pd.concat([counts, frequencies], axis=1)
        res.columns = ["频数", "百分比(%)"]
        res['累计百分比'] = res['百分比(%)'].cumsum()
        return get_result(res)

    frequency_res = []
    index_name_dict = dict()
    # j_arr = json.loads(index_name_json.titles)
    j_arr = index_name_json.titles
    for i in j_arr:
        index_name_dict[i.get('index')] = i.get('title')
    for column, values in df.items():
        f_res = frequency_analysis(df[column])
        frequency_res.append({'data_index': column, 'title': index_name_dict[column], 'datas': f_res})
    return frequency_res


class FrequencyAnalysis(object):
    def __init__(self, df: pd.DataFrame, index_name_json: ut.WorkOrderExtend):
        self.df = df
        self.index_name_json = index_name_json

    def get_view_struct(self, obj: pd.DataFrame):
        """
        获取前端需要的结结构
        :param obj:
        :return:
        """
        output = []
        for index, row in obj.iterrows():
            output.append({'row_key': str(index), 'values': {str(col): row[col] for col in obj.columns}})
        return output

    def frequency_analysis(self, inner_df: pd.DataFrame):
        counts = inner_df.value_counts().sort_values()
        frequencies = counts / counts.sum()
        # 输出结果
        res = pd.concat([counts, frequencies], axis=1)
        res.columns = ["频数", "百分比(%)"]
        res['累计百分比'] = res['百分比(%)'].cumsum()
        res['选项名称'] = ''
        return self.get_view_struct(res)

    def do_analysis_v2(self):
        """
        频数分析——V2
        :return:
        """
        df = self.df
        frequency_res = []
        title_maps = self.index_name_json.title_maps
        if not title_maps:  # 题目有问题
            return frequency_res
        for item_title in title_maps:
            item = wjx_explain_v2.ItemWjxOb(**item_title)
            # 多选和排序单独处理
            # 单选，下拉单选
            if item.sys_type == SysTypeEnum.SINGLE.value or SysTypeEnum.SCALE.value == item.sys_type:
                # 选项答案对应的名字
                options = item.options
                option_index_name_dict = dict()
                for option in options:
                    item_option = wjx_explain_v2.ItemWjxOb(**option)
                    option_index_name_dict[item_option.value] = item_option.name
                # 定义参数
                sum_percentage = 0  # 累计百分比
                f_res = []  # 最终选项结果数组
                cur_option_index = 0  # 当前选项的索引
                item_index = item.data_index[0]  # 当前题目在数据库中的索引
                # col_df = df[item_index]  # 当前着一列数据的值
                cur_data = df[item_index]
                # single_list = cur_data.to_list()
                # for x_i in range(len(single_list)):
                #     o = single_list[x_i]
                #     str_o = str(o)
                #     str_o_arr = str_o.split('^')
                #     cur_data[x_i] = str_o_arr[0]
                # col_df = cur_data
                # # col_df = df[item_index].str.split('^').str[0]
                # # 直接将答案和对应的个数转为dict
                # name_count_dict = col_df.value_counts().to_dict()
                # 过滤出仅包含 "^" 前面的数据
                filtered_data = []
                for item_num_value in cur_data:
                    if isinstance(item_num_value, str) and "^" in item_num_value:
                        filtered_data.append(item_num_value.split("^")[0])
                    else:
                        filtered_data.append(item_num_value)
                name_count_dict = dict(Counter(str(x) for x in filtered_data))
                for key, v in name_count_dict.items():
                    cur_option_index += 1
                    # 计算占总个数的百分比
                    percentage = (v / len(cur_data)) * 100
                    inner_dict = dict()
                    # option_name = str(key) if -3 != key else '跳过'
                    option_name = option_index_name_dict.get(str(key)) if -3 != key else '跳过'
                    # option_key = key
                    # if -3 == key:
                    #     option_name = '跳过'
                    # else:
                    #     k = str(key)
                    #     k_list = k.split('^')
                    #     if not k_list:
                    #         option_name = k
                    #     else:
                    #         option_key = k_list[0]
                    #         option_name = option_index_name_dict.get(str(k_list[0]))
                    #         if not option_name:
                    #             option_name = k
                    inner_dict['选项名称'] = option_name
                    inner_dict['选项答案'] = int(key)
                    inner_dict['频数'] = int(v)
                    inner_dict['百分比(%)'] = str(percentage)
                    sum_percentage += percentage
                    inner_dict['累计百分比(%)'] = str(sum_percentage)
                    f_res.append({'row_key': cur_option_index, 'values': inner_dict})
                f_res.sort(key=lambda x: x['values']['频数'], reverse=True)  # 根据频数分析的结果降序排列
                data_index = str(item.title_id) + '.' + str(cur_option_index)
                frequency_res.append({'data_index': data_index, 'title': item.title, 'datas': f_res})
            elif item.sys_type == SysTypeEnum.MULTIPLE.value:
                f_res = []
                options = item.options
                for cur_index in range(len(options)):
                    option = options[cur_index]
                    item_option = wjx_explain_v2.ItemWjxOb(**option)
                    item_index = item_option.data_index
                    # col_df = df[item_index]
                    cur_data = df[item_index]
                    # single_list = cur_data.to_list()
                    # for x_i in range(len(single_list)):
                    #     o = single_list[x_i]
                    #     str_o = str(o)
                    #     str_o_arr = str_o.split('^')
                    #     cur_data[x_i] = str_o_arr[0]
                    # col_df = cur_data
                    # # 计算1的个数
                    # count_ones = col_df.value_counts().get('1', 0)
                    count_ones = sum(cur_data.apply(lambda x: bool(re.match(r'^1(?!1)', str(x)))))
                    # 计算占总个数的百分比
                    percentage = (count_ones / len(cur_data)) * 100
                    inner_dict = dict()
                    inner_dict['选项答案'] = int(item_option.value)
                    inner_dict['选项名称'] = item_option.name
                    inner_dict['频数'] = int(count_ones)
                    inner_dict['百分比(%)'] = percentage
                    # sum_percentage += percentage
                    # inner_dict['累计百分比(%)'] = str(sum_percentage)
                    f_res.append({'row_key': str(cur_index), 'values': inner_dict})
                f_res.sort(key=lambda x: x['values']['频数'], reverse=True)  # 根据频数分析的结果降序排列
                sum_percentage = 0
                for f_o in f_res:
                    cur_values = f_o.get('values')
                    if cur_values:
                        percent = cur_values.get('百分比(%)')
                        sum_percentage += percent
                        cur_values['累计百分比(%)'] = sum_percentage
                    f_o['values'] = cur_values
                frequency_res.append({'data_index': item.title_id, 'title': item.title, 'datas': f_res})
            elif item.sys_type == SysTypeEnum.MULTIPLE_TEXT.value or SysTypeEnum.MATRIX_TEXT.value == item.sys_type:
                # 矩阵填空题 and 多项填空题 and 比重
                children = item.children
                for child in children:
                    cur_child_index = 0  # title_id的子id
                    sum_percentage = 0
                    f_res = []
                    child_obj = wjx_explain_v2.ItemWjxOb(**child)
                    item_index = child_obj.data_index
                    col_df = df[item_index]
                    # 直接将答案和对应的个数转为dict
                    name_count_dict = col_df.value_counts().to_dict()
                    for k, v in name_count_dict.items():
                        cur_child_index += 1
                        pass
                        # 计算占总个数的百分比
                        percentage = (v / len(col_df)) * 100
                        inner_dict = dict()
                        if -3 == k:
                            k = '跳过'
                        inner_dict['选项答案'] = k
                        inner_dict['选项名称'] = k
                        inner_dict['频数'] = int(v)
                        inner_dict['百分比(%)'] = str(percentage)
                        sum_percentage += percentage
                        inner_dict['累计百分比(%)'] = str(sum_percentage)
                        f_res.append({'row_key': cur_child_index, 'values': inner_dict})
                    f_res.sort(key=lambda x: x['values']['频数'], reverse=True)  # 根据频数分析的结果降序排列
                    frequency_res.append(
                        {'data_index': str(item.title_id) + '.' + str(item_index), 'title': child_obj.title,
                         'datas': f_res})
            elif item.sys_type == SysTypeEnum.SORTED.value:  # 排序
                options = item.options
                option_index_name_dict = dict()
                for option in options:
                    item_option = wjx_explain_v2.ItemWjxOb(**option)
                    option_index_name_dict[item_option.value] = item_option.name
                cur_df = df[item.data_index]
                # 获取 DataFrame 的形状
                num_rows, num_cols = cur_df.shape
                # 计算 DataFrame 的总格子数
                num_cells = num_rows * num_cols
                value_count_dict = dict()
                for index, row in cur_df.iterrows():
                    for col in cur_df.columns:
                        value = row[col]
                        if value_count_dict.get(value):
                            value_count_dict[value] += 1
                        else:
                            value_count_dict[value] = 1
                sum_percentage = 0  # 累计百分比
                f_res = []  # 最终选项结果数组
                cur_option_index = 0  # 当前选项的索引
                for key, v in value_count_dict.items():
                    cur_option_index += 1
                    # 计算占总个数的百分比
                    percentage = (v / num_cells) * 100
                    inner_dict = dict()
                    option_key = key
                    if -3 == key:
                        option_name = '跳过'
                    else:
                        k = str(key)
                        k_list = k.split('^')
                        if not k_list:
                            option_name = k
                        else:
                            option_key = k_list[0]
                            option_name = option_index_name_dict.get(str(k_list[0]))
                            if not option_name:
                                option_name = k
                    inner_dict['选项答案'] = int(option_key)
                    inner_dict['选项名称'] = option_name
                    inner_dict['频数'] = int(v)
                    inner_dict['百分比(%)'] = percentage
                    sum_percentage += percentage
                    inner_dict['累计百分比(%)'] = str(sum_percentage)
                    f_res.append({'row_key': cur_option_index, 'values': inner_dict})
                f_res.sort(key=lambda x: x['values']['频数'], reverse=True)  # 根据频数分析的结果降序排列
                data_index = str(item.title_id) + '.' + str(cur_option_index)
                frequency_res.append({'data_index': data_index, 'title': item.title, 'datas': f_res})
            elif SysTypeEnum.TEXT.value == item.sys_type:  # 填空题
                options = item.options
                for option in options:
                    cur_option_index = 0
                    sum_percentage = 0
                    f_res = []
                    item_option = wjx_explain_v2.ItemWjxOb(**option)
                    item_index = item_option.data_index
                    col_df = df[item_index]
                    # 直接将答案和对应的个数转为dict
                    name_count_dict = col_df.value_counts().to_dict()
                    for k, v in name_count_dict.items():
                        cur_option_index += 1
                        pass
                        # 计算占总个数的百分比
                        percentage = (v / len(col_df)) * 100
                        inner_dict = dict()
                        if -3 == k:
                            k = '跳过'
                        inner_dict['选项答案'] = k
                        inner_dict['选项名称'] = k
                        inner_dict['频数'] = int(v)
                        inner_dict['百分比(%)'] = str(percentage)
                        sum_percentage += percentage
                        inner_dict['累计百分比(%)'] = str(sum_percentage)
                        f_res.append({'row_key': cur_option_index, 'values': inner_dict})
                    f_res.sort(key=lambda x: x['values']['频数'], reverse=True)  # 根据频数分析的结果降序排列
                    frequency_res.append(
                        {'data_index': str(item.title_id) + '.' + str(cur_option_index), 'title': item_option.title,
                         'datas': f_res})
            elif SysTypeEnum.MATRIX.value == item.sys_type:  # 矩阵题
                children = item.children
                for child in children:
                    child_obj = wjx_explain_v2.ItemWjxOb(**child)
                    options = child_obj.options
                    option_index_name_dict = dict()
                    for option in options:
                        item_option = wjx_explain_v2.ItemWjxOb(**option)
                        option_index_name_dict[item_option.value] = item_option.name
                    # 定义参数
                    sum_percentage = 0  # 累计百分比
                    f_res = []  # 最终选项结果数组
                    cur_option_index = 0  # 当前选项的索引
                    item_index = child_obj.data_index  # 当前题目在数据库中的索引
                    col_df = df[item_index]  # 当前着一列数据的值
                    # 直接将答案和对应的个数转为dict
                    name_count_dict = col_df.value_counts().to_dict()
                    for k, v in name_count_dict.items():
                        cur_option_index += 1
                        pass
                        # 计算占总个数的百分比
                        percentage = (v / len(col_df)) * 100
                        inner_dict = dict()
                        option_key = k
                        if -3 == k:
                            option_name = '跳过'
                        else:
                            option_name = option_index_name_dict.get(str(k))
                        inner_dict['选项答案'] = option_key
                        inner_dict['选项名称'] = option_name
                        inner_dict['频数'] = int(v)
                        inner_dict['百分比(%)'] = str(percentage)
                        sum_percentage += percentage
                        inner_dict['累计百分比(%)'] = str(sum_percentage)
                        f_res.append({'row_key': cur_option_index, 'values': inner_dict})
                    f_res.sort(key=lambda x: x['values']['频数'], reverse=True)  # 根据频数分析的结果降序排列
                    frequency_res.append(
                        {'data_index': str(child_obj.title_id) + '.' + str(item_index), 'title': child_obj.title,
                         'datas': f_res})
            elif SysTypeEnum.MULTIPLE_MATRIX.value == item.sys_type:  # 矩阵多选
                children = item.children
                for child in children:
                    item_child = wjx_explain_v2.ItemWjxOb(**child)
                    # sum_percentage = 0
                    f_res = []
                    options = item_child.options
                    for cur_index in range(len(options)):
                        option = options[cur_index]
                        item_option = wjx_explain_v2.ItemWjxOb(**option)
                        item_index = item_option.data_index
                        col_df = df[item_index]
                        # 计算1的个数
                        count_ones = col_df.value_counts().get(1, 0)
                        # 计算占总个数的百分比
                        percentage = (count_ones / len(col_df)) * 100
                        inner_dict = dict()
                        inner_dict['选项答案'] = item_option.value
                        inner_dict['选项名称'] = item_option.name
                        inner_dict['频数'] = int(count_ones)
                        inner_dict['百分比(%)'] = percentage
                        f_res.append({'row_key': str(cur_index), 'values': inner_dict})
                    f_res.sort(key=lambda x: x['values']['频数'], reverse=True)  # 根据频数分析的结果降序排列
                    sum_percentage = 0
                    for f_o in f_res:
                        cur_values = f_o.get('values')
                        if cur_values:
                            percent = cur_values.get('百分比(%)')
                            sum_percentage += percent
                            cur_values['累计百分比(%)'] = sum_percentage
                        f_o['values'] = cur_values
                    data_index = str(item.title_id) + '.' + str(item_child.data_index)
                    frequency_res.append({'data_index': data_index, 'title': item_child.title, 'datas': f_res})
            elif SysTypeEnum.SLIDE.value == item.sys_type:  # 矩阵滑杆
                children = item.children
                for child in children:
                    cur_child_index = 0  # title_id的子id
                    sum_percentage = 0
                    f_res = []
                    child_obj = wjx_explain_v2.ItemWjxOb(**child)
                    item_index = child_obj.data_index
                    col_df = df[item_index]
                    # 直接将答案和对应的个数转为dict
                    name_count_dict = col_df.value_counts().to_dict()
                    for k, v in name_count_dict.items():
                        cur_child_index += 1
                        pass
                        # 计算占总个数的百分比
                        percentage = (v / len(col_df)) * 100
                        inner_dict = dict()
                        if -3 == k:
                            k = '跳过'
                        inner_dict['选项答案'] = k
                        inner_dict['选项名称'] = k
                        inner_dict['频数'] = int(v)
                        inner_dict['百分比(%)'] = str(percentage)
                        sum_percentage += percentage
                        inner_dict['累计百分比(%)'] = str(sum_percentage)
                        f_res.append({'row_key': cur_child_index, 'values': inner_dict})
                    f_res.sort(key=lambda x: x['values']['频数'], reverse=True)  # 根据频数分析的结果降序排列
                    frequency_res.append(
                        {'data_index': str(item.title_id) + '.' + str(item_index), 'title': child_obj.title,
                         'datas': f_res})
            elif SysTypeEnum.RATE.value == item.sys_type:  # 比重
                options = item.options
                for child in options:
                    cur_child_index = 0  # title_id的子id
                    sum_percentage = 0
                    f_res = []
                    child_obj = wjx_explain_v2.ItemWjxOb(**child)
                    item_index = child_obj.data_index
                    col_df = df[item_index]
                    # 直接将答案和对应的个数转为dict
                    name_count_dict = col_df.value_counts().to_dict()
                    for k, v in name_count_dict.items():
                        cur_child_index += 1
                        pass
                        # 计算占总个数的百分比
                        percentage = (v / len(col_df)) * 100
                        inner_dict = dict()
                        if -3 == k:
                            k = '跳过'
                        inner_dict['选项答案'] = k
                        inner_dict['选项名称'] = k
                        inner_dict['频数'] = int(v)
                        inner_dict['百分比(%)'] = str(percentage)
                        sum_percentage += percentage
                        inner_dict['累计百分比(%)'] = str(sum_percentage)
                        f_res.append({'row_key': cur_child_index, 'values': inner_dict})
                    f_res.sort(key=lambda x: x['values']['频数'], reverse=True)  # 根据频数分析的结果降序排列
                    frequency_res.append(
                        {'data_index': str(item.title_id) + '.' + str(item_index), 'title': child_obj.title,
                         'datas': f_res})
            elif SysTypeEnum.SINGLE_SLIDE.value == item.sys_type:  # 单项滑杆
                children = item.children
                for child in children:
                    cur_child_index = 0  # title_id的子id
                    sum_percentage = 0
                    f_res = []
                    child_obj = wjx_explain_v2.ItemWjxOb(**child)
                    item_index = child_obj.data_index
                    col_df = df[item_index]
                    # 直接将答案和对应的个数转为dict
                    name_count_dict = col_df.value_counts().to_dict()
                    for k, v in name_count_dict.items():
                        cur_child_index += 1
                        pass
                        # 计算占总个数的百分比
                        percentage = (v / len(col_df)) * 100
                        inner_dict = dict()
                        if -3 == k:
                            k = '跳过'
                        inner_dict['选项答案'] = k
                        inner_dict['选项名称'] = k
                        inner_dict['频数'] = int(v)
                        inner_dict['百分比(%)'] = str(percentage)
                        sum_percentage += percentage
                        inner_dict['累计百分比(%)'] = str(sum_percentage)
                        f_res.append({'row_key': cur_child_index, 'values': inner_dict})
                    f_res.sort(key=lambda x: x['values']['频数'], reverse=True)  # 根据频数分析的结果降序排列
                    frequency_res.append(
                        {'data_index': str(item.title_id) + '.' + str(item_index), 'title': child_obj.title,
                         'datas': f_res})
            elif SysTypeEnum.DESCRIPTION.value == item.sys_type:
                pass  # 对于描述性题目略过
            else:
                cur_index = item.data_index[0]  # 获取当前的数据索引
                f_res = self.frequency_analysis(df[cur_index])  # 获取当前列的数据，进行频数分析
                frequency_res.append({'data_index': item.title_id, 'title': item.title, 'datas': f_res})
        return frequency_res

    def do_analysis_v3(self):
        """
        频数分析——V2
        :return:
        """
        df = self.df
        frequency_res = []
        title_maps = self.index_name_json.title_maps
        if not title_maps:  # 题目有问题
            return frequency_res
        base_index = 0
        for item_title in title_maps:
            item = GenerateObj.conver_json_2_obj(item_title)
            # 多选和排序单独处理
            # 单选，下拉单选
            if item.sys_type == SysTypeEnum.SINGLE.value or SysTypeEnum.SCALE.value == item.sys_type or item.sys_type == SysTypeEnum.SINGLE_SELECT.value:
                # 选项答案对应的名字
                options = item.options
                option_index_name_dict = dict()
                for option in options:
                    item_option = GenerateObj.conver_json_2_obj(option)
                    option_index_name_dict[item_option.value] = item_option.name
                # 定义参数
                sum_percentage = 0  # 累计百分比
                f_res = []  # 最终选项结果数组
                cur_option_index = 0  # 当前选项的索引
                item_index = item.data_index[0] - base_index  # 当前题目在数据库中的索引
                # col_df = df[item_index]  # 当前着一列数据的值
                cur_data = df[item_index]
                # single_list = cur_data.to_list()
                # for x_i in range(len(single_list)):
                #     o = single_list[x_i]
                #     str_o = str(o)
                #     str_o_arr = str_o.split('^')
                #     cur_data[x_i] = str_o_arr[0]
                # col_df = cur_data
                # # col_df = df[item_index].str.split('^').str[0]
                # # 直接将答案和对应的个数转为dict
                # name_count_dict = col_df.value_counts().to_dict()
                # 过滤出仅包含 "^" 前面的数据
                filtered_data = []
                for item_num_value in cur_data:
                    if isinstance(item_num_value, str) and "^" in item_num_value:
                        filtered_data.append(int(item_num_value.split("^")[0]))
                    else:
                        filtered_data.append(int(item_num_value))
                name_count_dict = dict(Counter(str(x) for x in filtered_data))
                for key, v in name_count_dict.items():
                    # cur_value = pd.to_numeric(key, downcast='integer')
                    cur_value = key
                    cur_option_index += 1
                    # 计算占总个数的百分比
                    percentage = (v / len(cur_data)) * 100
                    inner_dict = dict()
                    # option_name = str(key) if -3 != key else '跳过'
                    option_name = option_index_name_dict.get(cur_value) if -3 != key else '跳过'
                    # option_key = key
                    # if -3 == key:
                    #     option_name = '跳过'
                    # else:
                    #     k = str(key)
                    #     k_list = k.split('^')
                    #     if not k_list:
                    #         option_name = k
                    #     else:
                    #         option_key = k_list[0]
                    #         option_name = option_index_name_dict.get(str(k_list[0]))
                    #         if not option_name:
                    #             option_name = k
                    inner_dict['选项名称'] = option_name
                    inner_dict['选项答案'] = cur_value
                    inner_dict['频数'] = int(v)
                    inner_dict['百分比(%)'] = str(percentage)
                    sum_percentage += percentage
                    inner_dict['累计百分比(%)'] = str(sum_percentage)
                    f_res.append({'row_key': cur_option_index, 'values': inner_dict})
                f_res.sort(key=lambda x: x['values']['频数'], reverse=True)  # 根据频数分析的结果降序排列
                data_index = str(item.title_id) + '.' + str(cur_option_index)
                frequency_res.append({'data_index': data_index, 'title': item.title, 'datas': f_res})
            elif item.sys_type == SysTypeEnum.MULTIPLE.value:
                f_res = []
                options = item.options
                for cur_index in range(len(options)):
                    option = options[cur_index]
                    item_option = GenerateObj.conver_json_2_obj(option)
                    item_index = item_option.data_index - base_index
                    # col_df = df[item_index]
                    cur_data = df[item_index]
                    # single_list = cur_data.to_list()
                    # for x_i in range(len(single_list)):
                    #     o = single_list[x_i]
                    #     str_o = str(o)
                    #     str_o_arr = str_o.split('^')
                    #     cur_data[x_i] = str_o_arr[0]
                    # col_df = cur_data
                    # # 计算1的个数
                    # count_ones = col_df.value_counts().get('1', 0)
                    count_ones = sum(cur_data.apply(lambda x: bool(re.match(r'^1(?!1)', str(x)))))
                    # 计算占总个数的百分比
                    percentage = (count_ones / len(cur_data)) * 100
                    inner_dict = dict()
                    inner_dict['选项答案'] = int(item_option.value)
                    inner_dict['选项名称'] = item_option.name
                    inner_dict['频数'] = int(count_ones)
                    inner_dict['百分比(%)'] = percentage
                    # sum_percentage += percentage
                    # inner_dict['累计百分比(%)'] = str(sum_percentage)
                    f_res.append({'row_key': str(cur_index), 'values': inner_dict})
                f_res.sort(key=lambda x: x['values']['频数'], reverse=True)  # 根据频数分析的结果降序排列
                sum_percentage = 0
                for f_o in f_res:
                    cur_values = f_o.get('values')
                    if cur_values:
                        percent = cur_values.get('百分比(%)')
                        sum_percentage += percent
                        cur_values['累计百分比(%)'] = sum_percentage
                    f_o['values'] = cur_values
                frequency_res.append({'data_index': item.title_id, 'title': item.title, 'datas': f_res})
            elif item.sys_type == SysTypeEnum.MULTIPLE_TEXT.value or SysTypeEnum.MATRIX_TEXT.value == item.sys_type:
                # 矩阵填空题 and 多项填空题 and 比重
                children = item.children
                for child in children:
                    cur_child_index = 0  # title_id的子id
                    sum_percentage = 0
                    f_res = []
                    child_obj = GenerateObj.conver_json_2_obj(child)
                    item_index = child_obj.data_index - base_index
                    col_df = df[item_index]
                    # 直接将答案和对应的个数转为dict
                    name_count_dict = col_df.value_counts().to_dict()
                    for k, v in name_count_dict.items():
                        cur_child_index += 1
                        pass
                        # 计算占总个数的百分比
                        percentage = (v / len(col_df)) * 100
                        inner_dict = dict()
                        if -3 == k:
                            k = '跳过'
                        inner_dict['选项答案'] = k
                        inner_dict['选项名称'] = k
                        inner_dict['频数'] = int(v)
                        inner_dict['百分比(%)'] = str(percentage)
                        sum_percentage += percentage
                        inner_dict['累计百分比(%)'] = str(sum_percentage)
                        f_res.append({'row_key': cur_child_index, 'values': inner_dict})
                    f_res.sort(key=lambda x: x['values']['频数'], reverse=True)  # 根据频数分析的结果降序排列
                    frequency_res.append(
                        {'data_index': str(item.title_id) + '.' + str(item_index), 'title': child_obj.title,
                         'datas': f_res})
            elif item.sys_type == SysTypeEnum.SORTED.value:  # 排序
                options = item.options
                option_index_name_dict = dict()
                for option in options:
                    item_option = GenerateObj.conver_json_2_obj(option)
                    option_index_name_dict[item_option.value] = item_option.name
                cur_columns = item.data_index
                if base_index:
                    cur_columns = [x - base_index for x in cur_columns]
                cur_df = df[cur_columns]
                # 获取 DataFrame 的形状
                num_rows, num_cols = cur_df.shape
                # 计算 DataFrame 的总格子数
                num_cells = num_rows * num_cols
                value_count_dict = dict()
                for index, row in cur_df.iterrows():
                    for col in cur_df.columns:
                        value = row[col]
                        if value_count_dict.get(value):
                            value_count_dict[value] += 1
                        else:
                            value_count_dict[value] = 1
                sum_percentage = 0  # 累计百分比
                f_res = []  # 最终选项结果数组
                cur_option_index = 0  # 当前选项的索引
                for key, v in value_count_dict.items():
                    cur_option_index += 1
                    # 计算占总个数的百分比
                    percentage = (v / num_cells) * 100
                    inner_dict = dict()
                    option_key = key
                    if -3 == key:
                        option_name = '跳过'
                    else:
                        k = str(key)
                        k_list = k.split('^')
                        if not k_list:
                            option_name = k
                        else:
                            option_key = k_list[0]
                            option_name = option_index_name_dict.get(str(k_list[0]))
                            if not option_name:
                                option_name = k
                    inner_dict['选项答案'] = int(option_key)
                    inner_dict['选项名称'] = option_name
                    inner_dict['频数'] = int(v)
                    inner_dict['百分比(%)'] = percentage
                    sum_percentage += percentage
                    inner_dict['累计百分比(%)'] = str(sum_percentage)
                    f_res.append({'row_key': cur_option_index, 'values': inner_dict})
                f_res.sort(key=lambda x: x['values']['频数'], reverse=True)  # 根据频数分析的结果降序排列
                data_index = str(item.title_id) + '.' + str(cur_option_index)
                frequency_res.append({'data_index': data_index, 'title': item.title, 'datas': f_res})
            elif SysTypeEnum.TEXT.value == item.sys_type:  # 填空题
                options = item.options
                for option in options:
                    cur_option_index = 0
                    sum_percentage = 0
                    f_res = []
                    item_option = GenerateObj.conver_json_2_obj(option)
                    item_index = item_option.data_index - base_index
                    col_df = df[item_index]
                    # 直接将答案和对应的个数转为dict
                    name_count_dict = col_df.value_counts().to_dict()
                    for k, v in name_count_dict.items():
                        cur_option_index += 1
                        pass
                        # 计算占总个数的百分比
                        percentage = (v / len(col_df)) * 100
                        inner_dict = dict()
                        if -3 == k:
                            k = '跳过'
                        inner_dict['选项答案'] = k
                        inner_dict['选项名称'] = k
                        inner_dict['频数'] = int(v)
                        inner_dict['百分比(%)'] = str(percentage)
                        sum_percentage += percentage
                        inner_dict['累计百分比(%)'] = str(sum_percentage)
                        f_res.append({'row_key': cur_option_index, 'values': inner_dict})
                    f_res.sort(key=lambda x: x['values']['频数'], reverse=True)  # 根据频数分析的结果降序排列
                    frequency_res.append(
                        {'data_index': str(item.title_id) + '.' + str(cur_option_index), 'title': item_option.title,
                         'datas': f_res})
            elif SysTypeEnum.MATRIX.value == item.sys_type:  # 矩阵题
                children = item.children
                for child in children:
                    child_obj = GenerateObj.conver_json_2_obj(child)
                    options = child_obj.options
                    option_index_name_dict = dict()
                    for option in options:
                        item_option = GenerateObj.conver_json_2_obj(option)
                        option_index_name_dict[item_option.value] = item_option.name
                    # 定义参数
                    sum_percentage = 0  # 累计百分比
                    f_res = []  # 最终选项结果数组
                    cur_option_index = 0  # 当前选项的索引
                    item_index = child_obj.data_index - base_index  # 当前题目在数据库中的索引
                    col_df = df[item_index]  # 当前着一列数据的值
                    # 直接将答案和对应的个数转为dict
                    name_count_dict = col_df.value_counts().to_dict()
                    for k, v in name_count_dict.items():
                        cur_option_index += 1
                        pass
                        # 计算占总个数的百分比
                        percentage = (v / len(col_df)) * 100
                        inner_dict = dict()
                        option_key = k
                        if -3 == k:
                            option_name = '跳过'
                        else:
                            option_name = option_index_name_dict.get(str(k))
                        inner_dict['选项答案'] = option_key
                        inner_dict['选项名称'] = option_name
                        inner_dict['频数'] = int(v)
                        inner_dict['百分比(%)'] = str(percentage)
                        sum_percentage += percentage
                        inner_dict['累计百分比(%)'] = str(sum_percentage)
                        f_res.append({'row_key': cur_option_index, 'values': inner_dict})
                    f_res.sort(key=lambda x: x['values']['频数'], reverse=True)  # 根据频数分析的结果降序排列
                    frequency_res.append(
                        {'data_index': str(child_obj.title_id) + '.' + str(item_index), 'title': child_obj.title,
                         'datas': f_res})
            elif SysTypeEnum.MULTIPLE_MATRIX.value == item.sys_type:  # 矩阵多选
                children = item.children
                for child in children:
                    item_child = GenerateObj.conver_json_2_obj(child)
                    # sum_percentage = 0
                    f_res = []
                    options = item_child.options
                    for cur_index in range(len(options)):
                        option = options[cur_index]
                        item_option = GenerateObj.conver_json_2_obj(option)
                        item_index = item_option.data_index - base_index
                        col_df = df[item_index]
                        # 计算1的个数
                        count_ones = col_df.value_counts().get(1, 0)
                        # 计算占总个数的百分比
                        percentage = (count_ones / len(col_df)) * 100
                        inner_dict = dict()
                        inner_dict['选项答案'] = item_option.value
                        inner_dict['选项名称'] = item_option.name
                        inner_dict['频数'] = int(count_ones)
                        inner_dict['百分比(%)'] = percentage
                        f_res.append({'row_key': str(cur_index), 'values': inner_dict})
                    f_res.sort(key=lambda x: x['values']['频数'], reverse=True)  # 根据频数分析的结果降序排列
                    sum_percentage = 0
                    for f_o in f_res:
                        cur_values = f_o.get('values')
                        if cur_values:
                            percent = cur_values.get('百分比(%)')
                            sum_percentage += percent
                            cur_values['累计百分比(%)'] = sum_percentage
                        f_o['values'] = cur_values
                    data_index = str(item.title_id) + '.' + str(item_child.data_index - base_index)
                    frequency_res.append({'data_index': data_index, 'title': item_child.title, 'datas': f_res})
            elif SysTypeEnum.SLIDE.value == item.sys_type:  # 矩阵滑杆
                children = item.children
                for child in children:
                    cur_child_index = 0  # title_id的子id
                    sum_percentage = 0
                    f_res = []
                    child_obj = GenerateObj.conver_json_2_obj(child)
                    item_index = child_obj.data_index - base_index
                    col_df = df[item_index]
                    # 直接将答案和对应的个数转为dict
                    name_count_dict = col_df.value_counts().to_dict()
                    for k, v in name_count_dict.items():
                        cur_child_index += 1
                        pass
                        # 计算占总个数的百分比
                        percentage = (v / len(col_df)) * 100
                        inner_dict = dict()
                        if -3 == k:
                            k = '跳过'
                        inner_dict['选项答案'] = k
                        inner_dict['选项名称'] = k
                        inner_dict['频数'] = int(v)
                        inner_dict['百分比(%)'] = str(percentage)
                        sum_percentage += percentage
                        inner_dict['累计百分比(%)'] = str(sum_percentage)
                        f_res.append({'row_key': cur_child_index, 'values': inner_dict})
                    f_res.sort(key=lambda x: x['values']['频数'], reverse=True)  # 根据频数分析的结果降序排列
                    frequency_res.append(
                        {'data_index': str(item.title_id) + '.' + str(item_index), 'title': child_obj.title,
                         'datas': f_res})
            elif SysTypeEnum.RATE.value == item.sys_type:  # 比重
                options = item.options
                for child in options:
                    cur_child_index = 0  # title_id的子id
                    sum_percentage = 0
                    f_res = []
                    child_obj = GenerateObj.conver_json_2_obj(child)
                    item_index = child_obj.data_index - base_index
                    col_df = df[item_index]
                    # 直接将答案和对应的个数转为dict
                    name_count_dict = col_df.value_counts().to_dict()
                    for k, v in name_count_dict.items():
                        cur_child_index += 1
                        pass
                        # 计算占总个数的百分比
                        percentage = (v / len(col_df)) * 100
                        inner_dict = dict()
                        if -3 == k:
                            k = '跳过'
                        inner_dict['选项答案'] = k
                        inner_dict['选项名称'] = k
                        inner_dict['频数'] = int(v)
                        inner_dict['百分比(%)'] = str(percentage)
                        sum_percentage += percentage
                        inner_dict['累计百分比(%)'] = str(sum_percentage)
                        f_res.append({'row_key': cur_child_index, 'values': inner_dict})
                    f_res.sort(key=lambda x: x['values']['频数'], reverse=True)  # 根据频数分析的结果降序排列
                    frequency_res.append(
                        {'data_index': str(item.title_id) + '.' + str(item_index), 'title': child_obj.title,
                         'datas': f_res})
            elif SysTypeEnum.SINGLE_SLIDE.value == item.sys_type:  # 单项滑杆
                children = item.children
                for child in children:
                    cur_child_index = 0  # title_id的子id
                    sum_percentage = 0
                    f_res = []
                    child_obj = GenerateObj.conver_json_2_obj(child)
                    item_index = child_obj.data_index - base_index
                    col_df = df[item_index]
                    # 直接将答案和对应的个数转为dict
                    name_count_dict = col_df.value_counts().to_dict()
                    for k, v in name_count_dict.items():
                        cur_child_index += 1
                        pass
                        # 计算占总个数的百分比
                        percentage = (v / len(col_df)) * 100
                        inner_dict = dict()
                        if -3 == k:
                            k = '跳过'
                        inner_dict['选项答案'] = k
                        inner_dict['选项名称'] = k
                        inner_dict['频数'] = int(v)
                        inner_dict['百分比(%)'] = str(percentage)
                        sum_percentage += percentage
                        inner_dict['累计百分比(%)'] = str(sum_percentage)
                        f_res.append({'row_key': cur_child_index, 'values': inner_dict})
                    f_res.sort(key=lambda x: x['values']['频数'], reverse=True)  # 根据频数分析的结果降序排列
                    frequency_res.append(
                        {'data_index': str(item.title_id) + '.' + str(item_index), 'title': child_obj.title,
                         'datas': f_res})
            elif SysTypeEnum.DESCRIPTION.value == item.sys_type:
                # 描述题，仅做占位使用
                # base_index += 1
                pass
            else:
                cur_index = item.data_index[0] - base_index  # 获取当前的数据索引
                f_res = self.frequency_analysis(df[cur_index])  # 获取当前列的数据，进行频数分析
                frequency_res.append({'data_index': item.title_id, 'title': item.title, 'datas': f_res})
        return frequency_res


class ReportFrequencyAnalysis(object):
    def __init__(self, df: pd.DataFrame):
        self.df = df

    def get_result(self, obj: pd.DataFrame) -> []:
        """
        获取前端需要的结结构
        :param obj:
        :return:
        """
        output = []
        for index, row in obj.iterrows():
            output.append({'row_key': str(index), 'values': {str(col): row[col] for col in obj.columns}})
        return output

    def frequency_analysis(self, inner_df: pd.DataFrame):
        names = []
        counts = inner_df.value_counts().sort_values()
        for k, v in counts.items():
            names.append(k)
        frequencies = counts / counts.sum()
        # 输出结果
        res = pd.concat([pd.Series(names, names), counts, frequencies], axis=1)
        res.columns = ["选项", "频数", "百分比(%)"]
        res['累计百分比'] = res['百分比(%)'].cumsum()
        return self.get_result(res)

    def do_analysis(self):
        frequency_res = []
        for column, _ in self.df.items():
            f_res = self.frequency_analysis(self.df[column])
            frequency_res.append({'data_index': column, 'title': column, 'datas': f_res})
        return frequency_res
